package com.example.dbcenter.conf.excutor;

import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;
import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelect;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelect;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.example.dbcenter.conf.tranlator.ExprTranslator;
import com.mongodb.DBObject;
import org.springframework.data.mongodb.core.query.Query;

import java.util.Iterator;
import java.util.List;

public class DbSelectExcutor extends DbExcutor{
    private Query query;
    private boolean isOrderBy = true;

    public DbSelectExcutor(String collectionName, Query query) {
        this.query = query;
        this.collectionName = collectionName;
    }

    @Override
    public String parseQueryFromMongo() {
        return null;
    }

    @Override
    public String parseQueryFromSql() {
        SQLSelect select = null;
        switch(this.SQLDBType) {
            case ORACLE:
                select = new OracleSelect();
                break;
            case SQLSERVER:
                select = new SQLServerSelect();
                break;
            default:
                select = new SQLSelect();
        }
        ((SQLSelect)select).setQuery(this.parseSelectQuery(this.collectionName, this.query));
        if (this.isOrderBy) {
            ((SQLSelect)select).setOrderBy(this.parseOrderBy(this.query));
        }
        SQLSelectStatement stmt = new SQLSelectStatement((SQLSelect)select);;
//        switch(this.SQLDBType) {
//            case ORACLE:
//                stmt = new OracleSelect( (SQLSelect)select);
//                break;
//            default:
//                stmt = new SQLSelectStatement((SQLSelect)select);
//        }

        return  getSql((SQLStatement)stmt);
    }
    private SQLSelectQuery parseSelectQuery(String collectionName, Query query) {
        SQLSelectQueryBlock queryBlock = null;
        switch(this.SQLDBType) {
            case ORACLE:
                queryBlock = new OracleSelectQueryBlock();
                break;
            case SQLSERVER:
                queryBlock = new SQLServerSelectQueryBlock();
                break;
            case MYSQL:
                queryBlock = new MySqlSelectQueryBlock();
                break;
            default:
                queryBlock = new SQLSelectQueryBlock();
        }

        if (query != null && query.getLimit() > 0 && queryBlock instanceof MySqlSelectQueryBlock) {
            MySqlSelectQueryBlock.Limit limit = new MySqlSelectQueryBlock.Limit();
            limit.setRowCount(new SQLNumberExpr(query.getLimit()));
            limit.setOffset(new SQLNumberExpr(query.getSkip()));
            ((MySqlSelectQueryBlock)queryBlock).setLimit(limit);
            ((MySqlSelectQueryBlock)queryBlock).setOrderBy(this.parseOrderBy(query));
            this.isOrderBy = false;
        }

        ((SQLSelectQueryBlock)queryBlock).setFrom(ExprTranslator.translateTableName(collectionName));
        this.parseSelectList(query, (SQLSelectQueryBlock)queryBlock);
        this.parseWhere(query, (SQLSelectQueryBlock)queryBlock);
        return (SQLSelectQuery)queryBlock;
    }

    private void parseSelectList(Query query, SQLSelectQueryBlock queryBlock) {
        List<SQLSelectItem> selectList = queryBlock.getSelectList();
        if (query != null && query.getFieldsObject() != null) {
            DBObject fieldObj = query.getFieldsObject();
            Iterator var9 = fieldObj.keySet().iterator();

            while(var9.hasNext()) {
                String key = (String)var9.next();
                Object value = fieldObj.get(key);
                if (value instanceof Integer && (Integer)value == 1) {
                    SQLSelectItem selectItem = new SQLSelectItem(ExprTranslator.translateKey(key), (String)null);
                    selectList.add(selectItem);
                }
            }
        } else {
            SQLSelectItem selectItem = new SQLSelectItem(new SQLAllColumnExpr(), (String)null);
            selectList.add(selectItem);
        }

    }

    private void parseWhere(Query query, SQLSelectQueryBlock queryBlock) {
        if (query != null && query.getQueryObject() != null) {
            DBObject queryObj = query.getQueryObject();
            queryBlock.setWhere(ExprTranslator.translateWhere(queryObj, this.SQLDBType));
        }

    }
    private SQLOrderBy parseOrderBy(Query query) {
        SQLOrderBy orderBy = new SQLOrderBy();
        if (query != null && query.getSortObject() != null) {
            DBObject sortObj = query.getSortObject();

            SQLSelectOrderByItem item;
            for(Iterator var4 = sortObj.keySet().iterator(); var4.hasNext(); orderBy.addItem(item)) {
                String key = (String)var4.next();
                item = new SQLSelectOrderByItem();
                item.setExpr(ExprTranslator.translateKey(key));
                Integer value = (Integer)sortObj.get(key);
                if (value == 1) {
                    item.setType(SQLOrderingSpecification.ASC);
                } else if (value == -1) {
                    item.setType(SQLOrderingSpecification.DESC);
                }
            }
        }

        return orderBy;
    }
}
